/** Project : Sticky Notes Plus */
/** Author  : Sainagakishore Srikantham */
/** Email   : ssn.kishore@gmail.com */

/** File    : StickyNotesUIMgr.cpp */
/** Purpose : This file contains the definition for the class CStickyNotesUIMgr which is primarily responsible to deal
              with all the UI componens of the project */

#include <QMenu>
#include <QAction>
#include <QSystemTrayIcon>
#include <QMessageBox>
#include <QString>
#include <QApplication>
#include <cstdlib>
#include <vector>
#include <fstream>

#include "StickyNotesUIMgr.h"
#include "StickyNotesLoginMgr.h"
#include "StickyNote.h"
#include "StickyNotesPlus.h"
#include "StickyNotesDataMgr.h"
#include "StickyToDoList.h"
#include "StickyAction.h"

using std::vector;
using std::fstream;
using std::ios;

/** Constructor of the class */
CStickyNotesUIMgr::CStickyNotesUIMgr()
{
    /** Creating "actions" */
    iQuitAction = new QAction(tr("&Quit Sticky Notes Plus"), this);
    iShowAllNotes = new QAction(tr("&Show All Notes"), this);
    iDeleteAllNotes = new QAction(tr("&Delete All Notes"), this);
    iHideAllNotes = new QAction(tr("&Hide All Notes"), this);
    iHideAllNotes->setEnabled(false);

    iDonateAction = new QAction(tr("&Donate"), this);

    iAddDateNoteAction = new QAction(tr("&Date Note"), this);
    iAddHourNoteAction = new QAction(tr("&Hour Note"), this);
    iAddGenericNoteAction = new QAction(tr("&Generic Note"), this);
    iPreferencesAction = new QAction(tr("&Preferences"), this);
    iAboutAction = new QAction(tr("About"), this);

    /** Creating the system tray context menu */
    iSystemTrayMenu = new QMenu(this);

    iAddNoteMenu = iSystemTrayMenu->addMenu(tr("&Create New Note"));
    iAddNoteMenu->addAction(iAddDateNoteAction);
    iAddNoteMenu->addSeparator();
    iAddNoteMenu->addAction(iAddHourNoteAction);
    iAddNoteMenu->addSeparator();
    iAddNoteMenu->addAction(iAddGenericNoteAction);
    iSystemTrayMenu->addSeparator();

    iSystemTrayMenu->addAction(iShowAllNotes);
    iSystemTrayMenu->addAction(iHideAllNotes);
    iSystemTrayMenu->addSeparator();

    iSystemTrayMenu->addAction(iDeleteAllNotes);
    iSystemTrayMenu->addSeparator();

    iSystemTrayMenu->addAction(iDonateAction);
    iSystemTrayMenu->addSeparator();

    iSystemTrayMenu->addAction(iPreferencesAction);
    iSystemTrayMenu->addSeparator();

    iSystemTrayMenu->addAction(iAboutAction);
    iSystemTrayMenu->addSeparator();

    iMyNotesMenu = iSystemTrayMenu->addMenu(tr("&My Notes"));
    iSystemTrayMenu->addSeparator();

    iSystemTrayMenu->addAction(iQuitAction);

    /** Creating the system tray icon */
    iSystemTrayIcon = new CStickySystemTrayIcon(this);
    iSystemTrayIcon->setToolTip(tr("Sticky Notes Plus\nVersion 0.4.2"));

    iSystemTrayIcon->setContextMenu(iSystemTrayMenu);
    iSystemTrayIcon->setIcon(CStickyNotesPlus::GetNotesIcon());
    iSystemTrayIcon->show();

    this->setWindowIcon(CStickyNotesPlus::GetNotesIcon());
}

/** Destructor of the class */
CStickyNotesUIMgr::~CStickyNotesUIMgr()
{
    /** Actions */
    if(iQuitAction)
    {
        delete iQuitAction;
        iQuitAction = NULL;
    }
    if(iShowAllNotes)
    {
        delete iShowAllNotes;
        iShowAllNotes = NULL;
    }
    if(iHideAllNotes)
    {
        delete iHideAllNotes;
        iHideAllNotes = NULL;
    }
    if(iDonateAction)
    {
        delete iDonateAction;
        iDonateAction = NULL;
    }
    if(iAddDateNoteAction)
    {
        delete iAddDateNoteAction;
        iAddDateNoteAction = NULL;
    }
    if(iAddHourNoteAction)
    {
        delete iAddHourNoteAction;
        iAddHourNoteAction = NULL;
    }
    if(iAddGenericNoteAction)
    {
        delete iAddGenericNoteAction;
        iAddGenericNoteAction = NULL;
    }
    if(iPreferencesAction)
    {
        delete iPreferencesAction;
        iPreferencesAction = NULL;
    }

    /** Menus */
    if(iSystemTrayMenu)
    {
        delete iSystemTrayMenu;
        iSystemTrayMenu = NULL;
    }

    /** Systray Icon */
    if(iSystemTrayIcon)
    {
        delete iSystemTrayIcon;
        iSystemTrayIcon = NULL;
    }
}

/** Creates the "my notes" sub-menu items */
void CStickyNotesUIMgr::CreateMyNotes(int aNumberOfNotes)
{
    if(aNumberOfNotes > 0)
    {
        vector<CStickyNote*>::iterator notesBeginIterator = CStickyNotesPlus::GetInstance()->GetDataMgr()->GetNotesBeginIterator();
        
        for(int i=0; i<aNumberOfNotes; ++i)
        {
            CStickyAction* stickyAction = new CStickyAction(i, (*notesBeginIterator)->GetTitle(), this);
            iStickyActions.push_back(stickyAction);
            iMyNotesMenu->addAction(stickyAction);

            connect(stickyAction, SIGNAL(triggered()), stickyAction, SLOT(ActionTriggered()));
            ++notesBeginIterator;
        }
    }
}

/** Registers the "actions" or signals and slots associated with different UI components */
void CStickyNotesUIMgr::RegisterActions()
{
    /** Actions associated with the systray icon context menu */
    connect(iAddDateNoteAction, SIGNAL(triggered()), this, SLOT(AddDateNoteTriggered()));
    connect(iAddHourNoteAction, SIGNAL(triggered()), this, SLOT(AddHourNoteTriggered()));
    connect(iAddGenericNoteAction, SIGNAL(triggered()), this, SLOT(AddGenericTriggered()));

    connect(iHideAllNotes, SIGNAL(triggered()), this, SLOT(HideAllTriggered()));
    connect(iShowAllNotes, SIGNAL(triggered()), this, SLOT(ShowAllTriggered()));
    connect(iDeleteAllNotes, SIGNAL(triggered()), this, SLOT(DeleteAllTriggered()));
    connect(iDonateAction, SIGNAL(triggered()), this, SLOT(DonateTriggered()));
    connect(iPreferencesAction, SIGNAL(triggered()), this, SLOT(PreferencesTriggered()));
    connect(iAboutAction, SIGNAL(triggered()), this, SLOT(AboutTriggered()));
    connect(iQuitAction, SIGNAL(triggered()), this, SLOT(SaveAndQuit()));

    /** For the Systray Icon */
    connect(iSystemTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
            this, SLOT(IconActivated(QSystemTrayIcon::ActivationReason)));
}

/** Displays a pop up containing the login information of the user */
void CStickyNotesUIMgr::DisplayLoginInfo()
{
    QString loginDuration = CStickyNotesLoginMgr::GetInstance()->GetLoginDuration();
    iSystemTrayIcon->showMessage(tr("Login Information"),
                                 loginDuration, QSystemTrayIcon::Information);
}

/** Display the TO DO list */
void CStickyNotesUIMgr::DisplayToDoList()
{
    CStickyToDoList* stickyTodoList = CStickyNotesPlus::GetInstance()->GetToDoList();

    stickyTodoList->SetTimerInactive();
    if(stickyTodoList->isVisible())
    {
        stickyTodoList->hide();
        stickyTodoList->SaveAllTasks();
    }
    else
    {
        stickyTodoList->show();
    }
}

/** Overriden function that enables / disables menu items from the systray context menu */
void CStickyNotesUIMgr::setVisible(bool visible)
{
    QDialog::setVisible(visible);
}

/** Called when the user clicks on the systray icon */
void CStickyNotesUIMgr::IconActivated(QSystemTrayIcon::ActivationReason aReason)
{
    switch (aReason) {
    case QSystemTrayIcon::Trigger:
        DisplayLoginInfo();
    case QSystemTrayIcon::DoubleClick:
        break;
    case QSystemTrayIcon::MiddleClick:
        DisplayToDoList();
        break;
    default:
        ;
    }
}

/** Called when the 'Hide All Notes' item from the systray context menu is selected */
void CStickyNotesUIMgr::HideAllTriggered()
{
    CStickyNotesDataMgr* dataMgr = CStickyNotesPlus::GetInstance()->GetDataMgr();

    vector<CStickyNote*>::iterator notesBeginIterator = dataMgr->GetNotesBeginIterator();
    vector<CStickyNote*>::iterator notesEndIterator = dataMgr->GetNotesEndIterator();

    while(notesBeginIterator != notesEndIterator)
    {
        (*notesBeginIterator)->hide();
        ++notesBeginIterator;
    }
    iHideAllNotes->setEnabled(false);
    iShowAllNotes->setEnabled(true);

    /** Save the notes, just in case anything was modified */
    dataMgr->SaveAllNotes();
}

/** Called when the 'Show All Notes' item from the systray context menu is selected */
void CStickyNotesUIMgr::ShowAllTriggered()
{
    CStickyNotesDataMgr* dataMgr = CStickyNotesPlus::GetInstance()->GetDataMgr();

    vector<CStickyNote*>::iterator notesBeginIterator = dataMgr->GetNotesBeginIterator();
    vector<CStickyNote*>::iterator notesEndIterator = dataMgr->GetNotesEndIterator();

    if(notesBeginIterator == notesEndIterator)
    {
        QMessageBox::information(this, tr("Sticky Notes Plus"),
                                 tr("You haven't created any notes yet. Get started!"));
        return;
    }

    while(notesBeginIterator != notesEndIterator)
    {
        (*notesBeginIterator)->show();
        ++notesBeginIterator;
    }

    iHideAllNotes->setEnabled(true);
    iShowAllNotes->setEnabled(false);
}

/** Called when the 'Show All Notes' item from the systray context menu is selected */
void CStickyNotesUIMgr::DeleteAllTriggered()
{
    if(CStickyNotesPlus::GetInstance()->GetDataMgr()->GetNumberOfNotes() > 0)
    {
        int keepIt = 0;

        keepIt = QMessageBox::question(this, tr("Sticky Notes Plus"),
                                       tr("This action cannot be reverted. Continue?"),
                                       tr("Yes, go ahead"),
                                       tr("No, hold on!!"), 0, 0, 1);

        if(!keepIt) /** Wishes to delete the note */
        {
            /** Clearing the file */
            fstream binaryFile("StickyNotesPlus.dat",ios::out|ios::binary);
            binaryFile.close();

            /** Clearing the vector */
            CStickyNotesDataMgr* dataMgr = CStickyNotesPlus::GetInstance()->GetDataMgr();
            dataMgr->DeleteAllNotes();
        }

        iHideAllNotes->setEnabled(false);
        iShowAllNotes->setEnabled(true);
    }
    else
    {
        QMessageBox::information(this, tr("Sticky Notes Plus"),
                                 tr("Sorry, but there are no notes to delete!"));
    }
}

/** Called when the 'Hour Note' item from the systray context menu is selected */
void CStickyNotesUIMgr::AddHourNoteTriggered()
{
    if(!iHideAllNotes->isEnabled())
        iHideAllNotes->setEnabled(true);

    CStickyNotesPlus::GetInstance()->GetDataMgr()->AddNote(STICKY_EXPIRY_IN_HOURS);

}

/** Called when the 'Date Note' item from the systray context menu is selected */
void CStickyNotesUIMgr::AddDateNoteTriggered()
{
    // open this later

    /*if(!iHideAllNotes->isEnabled())
        iHideAllNotes->setEnabled(true);*/

    QMessageBox::information(this, tr("Sticky Notes Plus :: Create New Note"),
                             tr("Under Construction!"));
}

/** Called when the 'Generic' item from the systray context menu is selected */
void CStickyNotesUIMgr::AddGenericTriggered()
{
    if(!iHideAllNotes->isEnabled())
        iHideAllNotes->setEnabled(true);

    CStickyNotesPlus::GetInstance()->GetDataMgr()->AddNote(STICKY_GENERIC_NOTE);
}

/** Called when the 'Donate' item from the systray context menu is selected */
void CStickyNotesUIMgr::DonateTriggered()
{
    QMessageBox::information(this, tr("Sticky Notes Plus :: Donate"),
                             tr("Thank You for your gesture. We'll be accepting donations soon!"));
}

/** Called when the 'Preferences' item from the systray context menu is selected */
void CStickyNotesUIMgr::PreferencesTriggered()
{
    QMessageBox::information(this, tr("Sticky Notes Plus :: Preferences"),
                             tr("Under Construction!"));
}

/** Called when the 'About' item from the systray context menu is selected */
void CStickyNotesUIMgr::AboutTriggered()
{
    QMessageBox::information(this, tr("Sticky Notes Plus :: About"),
                             tr("Sticky Notes Plus version 0.4.2\nDeveloper: Sai Srikantham (ssn.kishore@gmail.com)\nAll rights reserved"));
}

/** Called when the 'Quit' item from the systray context menu is selected */
void CStickyNotesUIMgr::SaveAndQuit()
{
    CStickyNotesPlus::GetInstance()->GetDataMgr()->SaveAllNotes();
    CStickyNotesPlus::GetInstance()->GetToDoList()->SaveAllTasks();
    exit(EXIT_SUCCESS);
}

/** Evaluates if the 'Hide All Notes' option of the systray should be active */
void CStickyNotesUIMgr::EvaluateShowNHideAll()
{
    CStickyNotesDataMgr* dataMgr = CStickyNotesPlus::GetInstance()->GetDataMgr();

    vector<CStickyNote*>::iterator notesBeginIterator = dataMgr->GetNotesBeginIterator();
    vector<CStickyNote*>::iterator notesEndIterator = dataMgr->GetNotesEndIterator();

    bool atLeastOneHidden = false;
    bool atLeastOneVisible = false;

    if(notesBeginIterator != notesEndIterator)
    {
        while(notesBeginIterator != notesEndIterator)
        {
            if((*notesBeginIterator)->isVisible())
                atLeastOneVisible = true;
            else
                atLeastOneHidden = true;

            ++notesBeginIterator;
        }

        /** At least one not is still visible to the user, so 'Hide All' should be enabled */
        if(atLeastOneVisible)
        {
            iHideAllNotes->setEnabled(true);
            if(atLeastOneHidden)
                iShowAllNotes->setEnabled(true);
            else
                iShowAllNotes->setEnabled(false);
        }
        else
        {
            iHideAllNotes->setEnabled(false);
            if(atLeastOneHidden)
                iShowAllNotes->setEnabled(true);
            else
                iShowAllNotes->setEnabled(false);
        }
    }
    else
    {
        iShowAllNotes->setEnabled(true);
        iHideAllNotes->setEnabled(false);
    }
}

/** CStickySystemTrayIcon definition */

/** Constructor */
CStickySystemTrayIcon::CStickySystemTrayIcon(QWidget* aParent):QSystemTrayIcon(aParent)
{
}

/** This function catches all the events sent to this widget */
bool CStickySystemTrayIcon::event(QEvent *event)
{
    if (event->type() == QEvent::ToolTip) /** When the tool tip is to be displayed */
    {
       CStickyToDoList* stickyTodoList = CStickyNotesPlus::GetInstance()->GetToDoList();
       stickyTodoList->show();
       stickyTodoList->StartTimer();
    }
    return true;
}
